package sv.com.administrador.seguros.web.util;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import org.apache.commons.lang.StringUtils;
import org.hibernate.EntityMode;
import org.hibernate.SessionFactory;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.proxy.HibernateProxy;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.stereotype.Component;

import sv.com.administrador.seguros.annotation.WebProperty;
import sv.com.administrador.seguros.exception.WebException;

@Component
public class WebUtility extends WebUtilityConstants {
	
	private static ShaPasswordEncoder passwordEncoder;

	@Resource
	private void setPasswordEncoder(ShaPasswordEncoder passwordEncoder){
		WebUtility.passwordEncoder = passwordEncoder;
		
	}
	
	public static boolean isEmptyList(List<?> list){
		return list == null || list.isEmpty();
	}
	
	public static String getExceptionMessage(Throwable e){
		if(e == null || StringUtils.isEmpty(e.getMessage())) return DEFAULT_ERROR_MESSAGE;
		return e.getMessage();
	}
	
	public static String getHashedString(String usuario, String salt) throws WebException {
		String hashedString = StringUtils.EMPTY;
		try {
			usuario = StringUtils.upperCase(usuario);
			hashedString = passwordEncoder.encodePassword(salt, usuario);
		}
		catch (Exception e) {
			logger.error("Error encriptando cadena", e);
			throw new WebException("Error encriptando cadena");
		}
		return hashedString;
	}

	public static void preProcessBeforeSaveOrUpdate(Object object, SessionFactory session) throws WebException {
		try {
			if(object instanceof HibernateProxy)
				object = ((HibernateProxy)object).getHibernateLazyInitializer().getImplementation();
			Field[] fields = object.getClass().getDeclaredFields();
			Class<?> clazz = null;
			Object value = null;
			Serializable id = null;
			ClassMetadata classMetadata = null;
			WebProperty webProperty = null;
			ManyToOne manyToOne = null;
			Column column = null;
			Id idColumn = null;
			for (Field field : fields) {
				webProperty = field.getAnnotation(WebProperty.class);
				manyToOne = field.getAnnotation(ManyToOne.class);
				column = field.getAnnotation(Column.class);
				idColumn = field.getAnnotation(Id.class);
				field.setAccessible(true);
				value = field.get(object);
				if (value == null) continue;
				if (manyToOne != null) {
					classMetadata = session.getClassMetadata(value.getClass());
					if (classMetadata != null) {
						id = classMetadata.getIdentifier(value, EntityMode.POJO);
						if (id == null) field.set(object, null);
					}
				}
				if(idColumn != null) {
					if(value != null && value.equals(0L)){
						field.set(object, null);
					}
				}
				if (webProperty != null && webProperty.skipUppercase()) continue;
				clazz = field.getType();
				if (String.class.equals(clazz)) {
					field.set(object, StringUtils.upperCase((String) value));
				}
				if (column != null) {
					int length = column.length();
					if (length == 1) {
						if ("true".equals(value)) field.set(object, "1");
						else if ("false".equals(value)) field.set(object, "0");
					}
				}
			}
		}
		catch (Exception e) {
			logger.error("Error ejecutando pre-procesos antes de guardar objeto: " + e.getMessage(), e);
			throw new WebException(WebUtility.DEFAULT_ERROR_MESSAGE);
		}
	}
}
